errorcheckflag .EQU TRUE

;routines to check errors after a mySWI via the V-flag

 .IF errorcheckflag 
 B formulafunctionstart

;    error, if errorflag==1
; no error, if errorflag==0
;DECLARE INT errorflag
errorflag     .WORD 0 
; RiscOS errorblock
;DECLARE CHARPTR errorblock
errorblock    .WORD 0

formulaerrorcheck
   BVS formulaerror
   MOV tempregister,#0
   STR tempregister,errorflag
   B   formulaerrorback
formulaerror
   STR R0,errorblock
   MOV tempregister,#1
   STR tempregister,errorflag
formulaerrorback
   MOV PC,R14
   MOV R0,R0
formulafunctionstart
 .ENDC

 .MACRO errorcheck
  .IF errorcheckflag
   STR R14,\temp
   BL formulaerrorcheck
   LDR R14,\temp
   B \ready
\temp .WORD 0
\ready
  .ENDC
 .ENDM  

 .MACRO perror
  LD  tempregister,errorflag
  CMP tempregister,#1
  BNE \ready
  STR R0,\formulatemp0  
  LD  R0,errorblock
  SWI OS_GenerateError
  LDR  R0,\formulatemp0
  B \ready
\formulatemp0
\ready
 .ENDM

; Macro to replace mySWI for save and restore R14 in Utilities
; use mySWI in Utilities instead of SWI

 .MACRO mySWI
  .IF UTILITY
   STR R14,\R14save
  .ENDC
  SWI %1
  .IF UTILITY
   LDR R14,\R14save
   B \skipR14save
\R14save .WORD 0
\skipR14save
  .ENDC
 .ENDM

;Macro to get the length of string [%2] into %1
;destroys tempregister 

 .MACRO strlenmacro
  MOV %1,#0
  MOV tempregister,#0
\loop
     LDRB tempregister,[%2,%1]
     ADD  %1,%1,#1
     CMP  tempregister,#0
     GOcond NE,\loop
  SUB %1,%1,#1
 .ENDM 

;Macro to copy a string from [R2] to [R1] number of copied chars into %1
;destroys R1,R2,R3,tempregister

 .MACRO strcpymacro
  MOV R3,R2
\loop
     LDRB tempregister,[R2]
     CMP  tempregister,#0
     STRB tempregister,[R1]
     GOcond EQ,\hupf
      ADD  R1,R1,#1
      ADD  R2,R2,#1
     GO \loop
\hupf 
  SUB %1,R2,R3 
 .ENDM

;DECLARE INT  strlen(CHARPTR sourcestring)

 .MACRO strlen
  LDR R0,[stackregister,#%2]
  strlenmacro R1,R0
  MOV %1,R1
 .ENDM

;DECLARE INT  strcpy(CHARPTR targetstring,CHARPTR sourcestring)

 .MACRO strcpy
  LDR R1,[stackregister,#%2]
  LDR R2,[stackregister,#%3]
  strcpymacro %1
 .ENDM

;DECLARE INT  strcmp(CHARPTR targetstring,CHARPTR sourcestring)

 .MACRO strcmp
  LDR R1,[stackregister,#%2]
  LDR R2,[stackregister,#%3]
  MOV R3,#0
  MOV tempregister,#0
\loop
    LDRB R3,[R1]
    LDRB tempregister,[R2]
    CMP  R3,tempregister
    MOVLT R0,#0
    SUBLT R0,R0,#1
    MOVGT R0,#1
    GOcond NE,\hupf2
       CMP  R3,#0
       GOcond EQ,\hupf1
    ADD R1,R1,#1
    ADD R2,R2,#1
    GO \loop
\hupf1
  MOV R0,#0
\hupf2        
  MOV %1,R0
 .ENDM

;DECLARE INT  strcat(CHARPTR targetstring,CHARPTR sourcestring)

 .MACRO strcat
  LDR R1,[stackregister,#%2]
  LDR R2,[stackregister,#%3]
  strlenmacro R4,R1
  ADD R1,R4,R1
  strcpymacro %1
 .ENDM

;DECLARE INT  strncpy(CHARPTR targetstring,CHARPTR sourcestring,INT length)

 .MACRO strncpy
  LDR R1,[stackregister,#%2]
  LDR R2,[stackregister,#%3]
  LDR R3,[stackregister,#%4]
  MOV R5,R2
  MOV R4,#0
  MOV R0,#0
\loop
     LDRB R0,[R2]
     CMP  R0,#0
     STRB R0,[R1]
     GOcond EQ,\hupf
        ADD  R1,R1,#1
        ADD  R2,R2,#1
        ADD  R4,R4,#1
        CMP R4,R3
        GOcond EQ,\hupf2
     GO \loop
\hupf2
  MOV R0,#0
  STRB R0,[R1]
\hupf  
  SUB %1,R2,R5
 .ENDM

;DECLARE VOID  writestr(CHARPTR string)

 .MACRO writestr
  LDR R0,[stackregister,#%2]
  mySWI XOS_Write0
;  errorcheck
 .ENDM

;DECLARE INT  readstr(CHARPTR string,INT maxstringlength)

 .MACRO readstr
  LDR R0,[stackregister,#%2]
  LDR R1,[stackregister,#%3]
  MOV R2,#0
  MOV R3,#255.
  mySWI XOS_ReadLine
  errorcheck
  MOV %1,R1  
 .ENDM

;Macro to convert numerical string %2 to integer %1 destroy R0,R1

 .MACRO string2intmacro
  MOV R0,%2 
  GO \hupf1 
\buffer1 .BLOCK 12.
 .ALIGN
\hupf1
  ADR R1,\buffer1
  MOV R2,#11.
  mySWI XOS_EvaluateExpression
  errorcheck
  MOV %1,R2
 .ENDM

;Macro to convert integer %2 to string %1 destroy R0,R1,R2,R3,R4
 
.MACRO int2stringmacro
  GO \hupf
\buffer .BLOCK 12.
 .ALIGN
\hupf
  ADR R4,\buffer
  MOV R2,#11. 
  MOV R0,%2
  MOV R1,R4
  mySWI XOS_BinaryToDecimal
  errorcheck
  MOV R3,#0
  STRB R3,[R4,R2]
  MOV %1,R4
.ENDM

;Macro to convert integer %2 to hexstring %1 destroy R0,R1,R2,R3,R4
 
.MACRO int2hexstringmacro
  GO \hupf
\buffer .BLOCK 11.
 .ALIGN
\hupf
  ADR R4,\buffer
  MOV R2,#9. 
  MOV R0,%2
  MOV R1,R4
  mySWI XOS_ConvertHex8
  errorcheck
  MOV %1,R4
.ENDM

;DECLARE INT string2int(CHARPTR string)

 .MACRO string2int
  LDR R3,[stackregister,#%2]
  string2intmacro R4,R3
  MOV %1,R4
 .ENDM  

;DECLARE CHARPTR int2string(INT number)

 .MACRO int2string
  LDR R5,[stackregister,#%2]
  int2stringmacro R6,R5
  MOV %1,R6
 .ENDM  

;DECLARE CHARPTR int2hexstring(INT number)

 .MACRO int2hexstring
  LDR R5,[stackregister,#%2]
  int2hexstringmacro R6,R5
  MOV %1,R6
 .ENDM  

;DECLARE VOID  writeint(INT number)

 .MACRO writeint
  LDR R5,[stackregister,#%2]
  int2stringmacro R0,R5
  mySWI XOS_Write0
;  errorcheck
 .ENDM 

;DECLARE VOID  writeinthex(INT number)

 .MACRO writeinthex
  LDR R5,[stackregister,#%2]
  int2hexstringmacro R0,R5
  mySWI XOS_Write0
;  errorcheck
 .ENDM 

;DECLARE INT  readint()

 .MACRO readint
  GO \hupf1 
\buffer2 .BLOCK 21
 .ALIGN
\hupf1
  ADR R4,\buffer2
  MOV R0,R4
  MOV R1,#20
  MOV R2,#0
  MOV R3,#255.
  mySWI XOS_ReadLine
  errorcheck
  string2intmacro R3,R4
  MOV %1,R3
 .ENDM 

;DECLARE CHAR getc()

 .MACRO getc
  mySWI XOS_ReadC
;  errorcheck
  MOV %1,R0
 .ENDM

;DECLARE VOID  putc(CHAR  character)

 .MACRO putc
  LDRB R0,[stackregister,#%2]
  mySWI XOS_WriteC
;  errorcheck
 .ENDM

;DECLARE INT  open(CHARPTR filename)

 .MACRO open
  MOV R0,#5
  LDR R1,[stackregister,#%2]
  mySWI XOS_File
  errorcheck
  CMP R0,#1
  GOcond EQ,\read
  CMP R0,#0
  GOcond EQ,\write
  mySWI XOS_WriteS
    .STRING " can't open file (directory)"
    .ALIGN
  MOV R0,R1
  mySWI XOS_Write0
\write    
  MOV R0,#11.
  LDR R1,[stackregister,#%2]
  MOV R2,#0
  MOV R4,#0
  MOV R5,#0
  mySWI XOS_File
  errorcheck
\read
  MOV R0,#0C4
  LDR R1,[stackregister,#%2]
  mySWI XOS_Find
  errorcheck
\ready
  MOV %1,R0
 .ENDM

;DECLARE INT  openw(CHARPTR filename)

 .MACRO openw
  MOV R0,#84
  LDR R1,[stackregister,#%2]
  mySWI XOS_Find
  errorcheck
  MOV %1,R0
 .ENDM

;DECLARE INT  openr(CHARPTR filename)

 .MACRO openr
  MOV R0,#44
  LDR R1,[stackregister,#%2]
  mySWI XOS_Find
  errorcheck
  MOV %1,R0
 .ENDM

;DECLARE VOID  close(INT filehandle)

 .MACRO close
  MOV R0,#0 
  LDR R1,[stackregister,#%2]
  mySWI XOS_Find
  errorcheck
 .ENDM

;DECLARE VOID  bput(INT filehandle,CHAR character)

 .MACRO bput
  LDR  R0,[stackregister,#%3]
  LDR  R1,[stackregister,#%2]
  mySWI XOS_BPut
  errorcheck
 .ENDM  

;DECLARE CHAR bget(INT filehandle)

 .MACRO bget
  LDR R1,[stackregister,#%2]
  mySWI XOS_BGet
  errorcheck
  MOV %1,R0   
 .ENDM  

;DECLARE INT fgets(CHARPTR buffer,INT filehandle,INT bufferlen)

 .MACRO fgets
  LDR R2,[stackregister,#%3]
  LDR R3,[stackregister,#%2]
  MOV R5,R3
  LDR R4,[stackregister,#%4]
\loop
   MOV R1,R2
   mySWI XOS_BGet
   errorcheck
   GOcond CS,\end
   CMP R0,#32.
   MOVLT R4,R3
   STRGEB R0,[R3]
   ADDGE R3,R3,#1
   CMP R4,R3
   GOcond NE,\loop
\end
  MOV R0,#0
  STRB R0,[R3]
  SUB %1,R3,R5
 .ENDM

;DECLARE INT fputs(INT filehandle,CHARPTR buffer)

 .MACRO fputs
  MOV R0,#2
  LDR R2,[stackregister,#%3]
  LDR R1,[stackregister,#%2]
  strlenmacro R3,R2
  ADD R8,R2,R3
  MOV R5,#10.
  STRB R5,[R8]
  ADD R3,R3,#1
  ADD R8,R8,#1
  LDRB R6,[R8]
  MOV R5,#0
  STRB R5,[R8]
  MOV R5,R3
  mySWI XOS_GBPB
  errorcheck
  STRB R6,[R8]
  SUB  R7,R8,#1
  MOV  R6,#0
  STRB R6,[R7]  
  SUB  %1,R5,R3
 .ENDM  

;DECLARE INT  eof(INT filehandle)

 .MACRO eof
  MOV R0,#127.
  LDR R1,[stackregister,#%2]
  mySWI XOS_Byte
  errorcheck
  MOV %1,R1
 .ENDM

;DECLARE VOID  system(CHARPTR cli_string)

 .MACRO system
  LDR R0,[stackregister,#%2]
  mySWI XOS_CLI
  errorcheck
 .ENDM

;DECLARE VOID cr()

 .MACRO cr
  mySWI XOS_NewLine
;  errorcheck
 .ENDM 


 .MACRO tailcpy 
  MOV R4,#0
  LDR R2,[stackregister,#%2]
  MOV R3,#0 
\loop
     LDRB R4,[R0,R3]
     STRB R4,[R2,R3] 
     ADD R3,R3,#1
     CMP R4,#0 
     GOcond NE,\loop
 .ENDM

;DECLARE VOID  getclitail(CHARPTR buffer)

 .MACRO getclitail
  .IF MODULE | SIMPLE_MODULE
   LADR R0,formulaclitail
  .ELSE
   mySWI XOS_GetEnv
   errorcheck
   MOV  R1,#0
\loop1
   LDRB R1,[R0]
   CMP R1,#20
   BNE \loop2
   CMP R1,#0
   BEQ \ready
   ADD R0,R0,#1
   B \loop1
\loop2
   LDRB R1,[R0]
   CMP R1,#20
   BEQ \loop3
   CMP R1,#0
   BEQ \ready
   ADD R0,R0,#1
   B \loop2
\loop3
   LDRB R1,[R0]
   CMP R1,#20
   BNE \ready
   CMP R1,#0
   BEQ \ready
   ADD R0,R0,#1
   B \loop3
\ready
  .ENDC 
  tailcpy %1,%2
 .ENDM

;DECLARE VOID  getargv(CHARPTR buffer)

 .MACRO getargv
  mySWI XOS_GetEnv
  errorcheck
  tailcpy %1,%2
 .ENDM

;DECLARE VOID  getenv(CHARPTR buffer,CHARPTR varstring,INT bufferlen)

 .MACRO getenv
  LDR R0,[stackregister,#%3]
  LDR R1,[stackregister,#%2]
  LDR R2,[stackregister,#%4]
  MOV R3,#0
  MOV R4,#0
  mySWI XOS_ReadVarVal
  errorcheck
 .ENDM
  
;DECLARE VOID  setenv(CHARPTR varstring,CHARPTR varval)

 .MACRO setenv
  LDR R0,[stackregister,#%2]
  LDR R1,[stackregister,#%3]
  strlenmacro R2,R1
  MOV R3,#0
  MOV R4,#0
  mySWI XOS_SetVarVal
  errorcheck
 .ENDM

; malloc will currently use SWI OS_Module 6 use free() before you exit !

;DECLARE CHARPTR malloc(INT length)

 .MACRO malloc
  LDR R3,[stackregister,#%2]
  MOV R0,#6.
  mySWI OS_Module
  errorcheck
  MOV %1,R2
 .ENDM

;DECLARE VOID free(CHARPTR allocedbuffer)

 .MACRO free
  LDR R2,[stackregister,#%2]
  MOV R0,#7.
  mySWI OS_Module
  errorcheck
 .ENDM
